home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-08 | 11.4 KB | 369 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWScrolr.cpp
- // Release Version: $ 1.0d11 $
- //
- // Copyright: © 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFrameW.hpp"
-
- #ifndef FWSCROLR_H
- #include "FWScrolr.h"
- #endif
-
- #ifndef FWPART_H
- #include "FWPart.h"
- #endif
-
- #ifndef FWFRAME_H
- #include "FWFrame.h"
- #endif
-
- #ifndef FWSCLNOT_H
- #include "FWSclNot.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWSCLBAR_H
- #include "FWSclBar.h"
- #endif
-
- // ----- OS Layer -----
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODTransform_xh
- #include <Trnsform.xh>
- #endif
-
- #ifndef SOM_ODWindow_xh
- #include <Window.xh>
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FW_FrameSegment
- #endif
-
- //========================================================================================
- // CLASS FW_CScroller
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::FW_CScroller(Environment* ev, FW_CView* view) :
- FW_MReceiver(),
- fView(view),
- fConnection(this),
- fScrollNotificationToken(0)
- {
- ODSession* session = fView->GetFrame(ev)->GetPart(ev)->GetSession(ev);
- fScrollNotificationToken = session->Tokenize(ev, FW_CScrollNotification::kName);
-
- fConnection.Connect();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::~FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::~FW_CScroller()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::RegisterScrollBar
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::RegisterScrollNotifier(Environment* ev, FW_MNotifier* notifier)
- {
- // create the interest for the scroll notification
- FW_CInterest interest(notifier, fScrollNotificationToken);
-
- // Setup the connection to scroll the frame's internal transform
- // This must be done before the scroller so that the frame is notified first
- fView->GetFrame(ev)->AddConnection(ev, interest);
-
- fConnection.AddInterest(interest);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::UnregisterScrollNotifier
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::UnregisterScrollNotifier(Environment* ev, FW_MNotifier* notifier)
- {
- FW_CInterest interest(notifier, fScrollNotificationToken);
- fConnection.RemoveInterest(interest);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::HandleNotification
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::HandleNotification(const FW_CNotification& notification)
- {
- Environment *ev = somGetGlobalEnvironment();
-
- const FW_CScrollNotification& scrollNotification = (FW_CScrollNotification&) notification;
-
- if (scrollNotification.ShouldScroll())
- {
- FW_CPoint delta;
-
- FW_CFixed fx0 = FW_IntToFixed(0);
- FW_CFixed fxDelta = scrollNotification.GetDelta();
-
- if (scrollNotification.GetDirection() == FW_CScrollNotification::kVertical)
- delta.Set(fx0, fxDelta);
- else
- delta.Set(fxDelta, fx0);
-
- this->ScrollRelative(ev, delta);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollRelative
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::ScrollRelative(Environment* ev, const FW_CPoint& by)
- {
- FW_CPoint scrollBy(-by);
-
- FW_CFrameFacetIterator ite(ev, fView->GetFrame(ev));
- for (ODFacet* facet = (ODFacet *) ite.First(ev);
- ite.IsNotComplete(ev); facet = (ODFacet *) ite.Next(ev))
- {
- this->ScrollDraw(ev, facet, scrollBy);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollDraw
- //----------------------------------------------------------------------------------------
- // [HLX] Need a try block
-
- void FW_CScroller::ScrollDraw(Environment* ev, ODFacet* facet, const FW_CPoint& by)
- {
- #ifdef FW_BUILD_MAC
- ODPlatformWindow platformWindow = facet->GetWindow(ev)->GetPlatformWindow(ev);
-
- GrafPtr port;
- ::GetPort(&port);
- ::SetPort(platformWindow);
- Point origin;
- origin.h = platformWindow->portRect.left;
- origin.v = platformWindow->portRect.top;
- ODRgnHandle clipRgn = ::NewRgn();
- ::GetClip(clipRgn);
-
- ::SetOrigin(0, 0);
-
- // [LSD] the scroller's fView is always the ContentView for now.
- FW_CAcquiredODShape aqScrollShape = fView->GetFrame(ev)->AcquireContentScrollShape(ev, by);
-
- // converts to window coordinates
- FW_CAcquiredODTransform aqWindowFrameTransform = facet->AcquireWindowFrameTransform(ev, NULL);
- aqScrollShape->Transform(ev, aqWindowFrameTransform);
-
- FW_SPlatformRect platformRect = FW_GetShapeBoundingBox(ev, aqScrollShape);
-
- // get clip shape in window coordinates & intersect with scrollShape
- FW_CAcquiredODShape aqAggregateClipShape = FW_CopyAndRelease(ev, facet->AcquireAggregateClipShape(ev, NULL));
- aqAggregateClipShape->Transform(ev, aqWindowFrameTransform);
-
- aqAggregateClipShape->Intersect(ev, aqScrollShape);
-
- RgnHandle aggregateClipRgn = aqAggregateClipShape->GetQDRegion(ev);
- ::SetClip(aggregateClipRgn);
-
- RgnHandle invalidRgn = ::NewRgn(); // will be adopted by aqInvalidShape. No need to dispose it
- ::ScrollRect(&platformRect, by.IntX(), by.IntY(), invalidRgn);
-
- FW_CAcquiredODShape aqInvalidShape = ::FW_NewODShape(ev, invalidRgn);
- aqInvalidShape->InverseTransform(ev, aqWindowFrameTransform);
-
- // ----- Validating all the embedded facets seems to make it a little bit faster
- FW_CFacetIterator ite(ev, facet, kODChildrenOnly, kODFrontToBack);
- for (ODFacet* embeddedFacet = ite.First(ev); ite.IsNotComplete(ev); embeddedFacet = ite.Next(ev))
- {
- embeddedFacet->Validate(ev, NULL, NULL);
- }
-
- // ----- Update the facet -----
- facet->Invalidate(ev, aqInvalidShape, NULL);
- facet->GetWindow(ev)->Update(ev);
-
- ::SetClip(clipRgn);
- ::DisposeRgn(clipRgn);
- ::SetOrigin(-origin.h, -origin.v);
- ::SetPort(port);
- #endif
-
- #ifdef FW_BUILD_WIN
- FW_DEBUG_MESSAGE("Needs to be redone");
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::UpdateScrollParameters
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::UpdateScrollParameters(Environment* ev, FW_Boolean notify)
- {
- FW_UNUSED(ev);
- }
-
- //========================================================================================
- // CLASS FW_CScrollBarScroller
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::FW_CScrollBarScroller(Environment* ev, FW_CView* view,
- FW_CScrollBar* horzSB, FW_CScrollBar* vertSB) :
- FW_CScroller(ev, view),
- fHorzSB(horzSB),
- fVertSB(vertSB)
- {
- if (fHorzSB)
- RegisterScrollNotifier(ev, fHorzSB);
- if (fVertSB)
- RegisterScrollNotifier(ev, fVertSB);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::~FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::~FW_CScrollBarScroller()
- {
- // Don't delete the scroll bars, we don't own them! The containing gadget
- // or frame owns them.
-
- Environment* ev = ::somGetGlobalEnvironment();
-
- if (fHorzSB)
- UnregisterScrollNotifier(ev, fHorzSB);
- if (fVertSB)
- UnregisterScrollNotifier(ev, fVertSB);
- }
-
- //----------------------------------------------------------------------------------------
- // PrivAdjustScrollBar
- //----------------------------------------------------------------------------------------
-
- static FW_Boolean PrivAdjustScrollBar(Environment* ev,
- FW_CScrollBar* sb,
- FW_CFixed contentExtent,
- FW_CFixed scrollerSize,
- FW_CFixed contentOffset,
- FW_Boolean notify)
- {
- FW_Boolean updateAllView = FALSE;
-
- FW_CFixed oldPos = sb->GetScrollPos(ev);
- FW_CFixed newPos;
-
- sb->SetMajorScrollUnits(ev, scrollerSize);
- sb->SetMinorScrollUnits(ev, scrollerSize.DividedByInt(10).RoundedToInt());
-
- FW_CFixed range = contentExtent - scrollerSize;
- if (range < FW_kFixed0)
- range = FW_kFixed0;
-
- if (range > FW_kFixed0) {
- sb->SetScrollMax(ev, sb->GetScrollMin(ev) + range);
-
- if (contentOffset + scrollerSize > contentExtent)
- contentOffset = range;
-
- sb->SetScrollPos(ev, range, contentOffset);
- newPos = sb->GetScrollPos(ev);
- }
- else {
- // scroller is bigger than content (after resizing frame for instance)
- // we must scroll back to the origin
- sb->SetScrollMax(ev, sb->GetScrollMin(ev));
- newPos = FW_kFixed0;
- }
-
- if (oldPos != newPos)
- {
- updateAllView = TRUE;
- if (notify)
- sb->ScrollPositionChanged(ev, newPos, newPos - oldPos, FALSE);
- }
-
- return updateAllView;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::UpdateScrollParameters
- //----------------------------------------------------------------------------------------
- // [LSD] this must be corrected to handle scaling...
-
- void FW_CScrollBarScroller::UpdateScrollParameters(Environment* ev, FW_Boolean notify)
- {
- FW_ASSERT(fView->IsContentView(ev)); // [LSD] fView should always be the ContentView
-
- FW_CScroller::UpdateScrollParameters(ev);
-
- // Need to think about how we can provide some default behavior for updating the
- // minor scroll units. [SCROLL]
-
- FW_CPoint scrollerSize(fView->GetSize(ev));
-
- // contentOffset used to compute the scroll position is based on the Internal Transform
- // minus the position of the ContentView
- FW_CPoint contentOffset(FW_kZeroPoint);
- fView->ViewToViewContent(ev, contentOffset);
-
- FW_CPoint contentExtent(fView->GetExtent(ev));
-
- FW_CFrame* frame = fView->GetFrame(ev);
-
- FW_CScrollBar* sb = GetScrollBar(ev, kVertical);
- if (sb && PrivAdjustScrollBar(ev, sb, contentExtent.y, scrollerSize.y, contentOffset.y, notify))
- {
- FW_CAcquiredODShape invalidShape = frame->AcquireContentScrollShape(ev, FW_CPoint(FW_kFixed0, FW_IntToFixed(1)));
- frame->GetODFrame(ev)->Invalidate(ev, invalidShape, NULL);
- }
-
- sb = GetScrollBar(ev, kHorizontal);
- if (sb && PrivAdjustScrollBar(ev, sb, contentExtent.x, scrollerSize.x, contentOffset.x, notify))
- {
- FW_CAcquiredODShape invalidShape = frame->AcquireContentScrollShape(ev, FW_CPoint(FW_IntToFixed(1), FW_kFixed0));
- frame->GetODFrame(ev)->Invalidate(ev, invalidShape, NULL);
- }
- }
-